// by Xeno

#define __del \
{deleteVehicle _x} forEach [_vehicle] + _crew
private ["_player", "_sidep", "_grp", "_vehicle", "_unit", "_crew","_target_route","_flying_height","_last_pos","_taxi_type","_player_pos","_air_taxis"];
if (!isServer) exitWith {};

_debug = (d_global_debug > 0);

if (isnil "DM_AirTaxi_FlyingHeight") then { DM_AirTaxi_FlyingHeight = 60; };
if (DM_AirTaxi_FlyingHeight < 50) then { DM_AirTaxi_FlyingHeight = 50; };
DM_AirTaxi_SelectedHeight = DM_AirTaxi_FlyingHeight;

// We can call this script in 3 ways:
// player call airtaxi
// [player,target] call airtaxi
// [player,[waypoint1, waypoint2, waypoint3]] call airtaxi
if (typename _this != "ARRAY") then {
	_player = _this;
} else {
	_player = _this select 0;
	If (count _this > 1) then {
		_target_route = _this select 1;
		// Now we check whether _target_route is a string (for fixed destinations) or one or more waypoints.
		if (typename _target_route == "STRING") then {
			// Until now only the 'BASE' string is used and the script defaults to returning to the base.
		} else {
			// We are in the case of one or more waypoints
			If (typename (_target_route select 0) != "ARRAY") then {
				// It is only 1 waypoint, so we need to enclose it in braces
				_target_route = [_target_route];
			};
		};
	};
	if (count _this > 2) then {
		if (typename (_this select 2) == typename(1)) then {
			DM_AirTaxi_SelectedHeight = (_this select 2);
			if (DM_AirTaxi_SelectedHeight < 50) then { DM_AirTaxi_SelectedHeight = 50; };
		};
	};
};
if (_debug) then { diag_log Format["(%1)[%2]: %3  player:%4   route:%5",diag_tickTime,"airtaxiserver2.sqf","Starting", _player, _target_route]; };
_sidep = side _player;
_player_pos = getPos _player;
// We pick one of the available taxi type up:
_taxi_type = x_taxi_aircraft call XfRandomArrayVal;

// If we didn't provide a target_route (like for a return to base), then we take the default AI landing position or a position near the flag
If (isNil "_target_route") then {
	_target_route = "BASE";
};
If (typename _target_route == typename("")) then {
	// _target_route = [d_pos_ai_landing_zone select 0];
	_base_landing_pos = [(getPos FLAG_BASE),_taxi_type,200] call XfFindLandingPosition;
	// We create a route with a single point
	_target_route = [_base_landing_pos];
};
// This will be the position where the vehicle spawns.
_dstart_pos = call XfGetRanPointOuterAir;
// We first check if an invisible H has been placed with the special name
if (!isNil "AirTaxiSpawnPosition") then {
	_dstart_pos = [AirTaxiSpawnPosition];
} else {
	// If there is a carrier, all air taxi spawn around it.
	if (!isNil "LHD_Center") then {
		_dstart_pos = [getPos LHD_Center, 400] call XfGetRanPointCircleAir;
	} else {
		// We take the closest random spot
		_min_dist = _dstart_pos distance _player_pos;
		for [{_i = 0},{_i < 15},{_i = _i + 1}] do {
			_test_pos = call XfGetRanPointOuterAir;
			if ((_test_pos distance _player_pos) < _min_dist) then {
				_dstart_pos = _test_pos;
				_min_dist = _dstart_pos distance _player_pos;
			};
		};
	};
};
_flying_height = DM_AirTaxi_SelectedHeight;
if (_debug) then { diag_log Format["(%1)[%2]: Start:%3  Side:%4  Height:%5",diag_tickTime,"airtaxiserver2.sqf",_dstart_pos, _sidep, _flying_height]; };

if (_debug) then { 
	diag_log "";
	diag_log Format["(%1)[%2]: %3 ",diag_tickTime,"airtaxiserver2.sqf","Route positions"];
	{
		diag_log Format["   - %1",_x];
	} foreach _target_route;
	diag_log "";
};

// Big step, we need to find suitable landing positions for the player pickup and for the final destination.
_last_pos = _target_route select ((count _target_route) - 1);
_last_pos = [_last_pos,_taxi_type,200] call XfFindLandingPosition;
_player_pos = [_player_pos,_taxi_type,200] call XfFindLandingPosition;
if (count _last_pos == 0) exitWith {["d_ataxi", [10,_player]] call XNetCallEvent; diag_log Format["(%1)[%2]: %3",diag_tickTime,"airtaxiserver2.sqf","The target position is not valid for landing"];};
if (count _player_pos == 0) exitWith {["d_ataxi", [10,_player]] call XNetCallEvent; diag_log Format["(%1)[%2]: %3",diag_tickTime,"airtaxiserver2.sqf","You are not standing in a valid zone for landing"];};

// We need to update the last pos with the valid position found
_target_route set [(count _target_route - 1),_last_pos];
// Mando scripts expect an array of positions
_player_pos = [_player_pos];

// The marker for the air taxi
["d_airtaxi_marker", [0,0,0],"ICON","ColorBlue",[0.5,0.5],"Air Taxi",0,"Dot","",0.01] call XfCreateMarkerGlobal;

// Now we know it's possible to land on both sites, so we start the execution

// First, we check again if the player has already called an air taxi.
_air_taxis = ["airtaxi_available",[]] call XNetGetJIP;
if (isNil "_air_taxis") then {_air_taxis=[]};
if (typeName _air_taxis != "ARRAY") then {_air_taxis=[]};

if (_debug) then { 
	diag_log format["Busy air taxis: %1", _air_taxis];
};
if (_player in _air_taxis) exitWith {["d_ataxi", [7,_player]] call XNetCallEvent;};
_air_taxis set [count _air_taxis, _player];
["airtaxi_available",_air_taxis] call XNetSetJIP;

_crew_start_pos = d_pos_ai_spawn select 0;
// We create a group for the crew and we create a vehicle of the type defined in x_taxi_aircraft.
// We make a civilian pilot to avoid AI enhancement scripts to pick it up and change its behavior. Plus it's equivalent to making it "Captive"
// _grp = ["CIV"] call x_creategroup;
_grp = [_sidep] call x_creategroup;
_spos = [_dstart_pos select 0, _dstart_pos select 1, (_flying_height + 300)];
_cdir = [_spos, position _player] call XfDirTo;
_vehicle = createVehicle [_taxi_type, _spos, [], 0, "FLY"];
_vehicle setPos _spos;
_vehicle setVelocity [2 * (sin _cdir), 2 * (cos _cdir), 0];
_vehicle setVariable ["asr_ai_sys_aiskill_exclude", true];
_vehicle setVariable ["zeu_AIBypass", true];
_grp addVehicle _vehicle;
_crew_type = switch (_sidep) do {
		case west: {"USMC_Soldier_Pilot"};
		case east: {"RU_Soldier_Pilot"};
		default {"RU_Pilot"};
	};
_unit = [_crew_type, _grp, _crew_start_pos] call XfCreateUnit;
// _unit = _grp createUnit [_crew_type, _spos, [], 0, "NONE"];
while {vehicle _unit == _unit} do {
	_unit setPos (getPos _vehicle);
	_unit moveinDriver _vehicle;
};
_crew = crew _vehicle;
_grp selectLeader (commander _vehicle);
_grp setCombatMode "BLUE";
_grp setBehaviour "CARELESS";
 // We set the crew captive so the vehicle is not a target as long as it is on the way to the player.
// As soon as the player get inside... the feast can begin :)
{
	_x setVariable ["BIS_noCoreConversations", true];
	_x setVariable ["zeu_AIBypass", true];
	_x setVariable ["asr_ai_sys_aiskill_exclude", true];
	_x setUnitAbility (0.9);
	_x setcaptive true;
	_x disableAI "TARGET";
	_x disableAI "AUTOTARGET";
	_x disableAI "FSM";
	_x allowfleeing 0;
} foreach _crew;
_unit = driver _vehicle;
d_allunits_add set [count d_allunits_add, _vehicle];
d_allunits_add set [count d_allunits_add, _unit];
_vehicle lockdriver true;

_fnTaxiGetOutHandler = {
	private ["_vec","_unit","_empty"];
	_vec = _this select 0;
	_empty = true;
	{
		If (isPlayer _x) ExitWith {_empty = false;};
	} foreach crew _vec;
	_vec setVariable ["airtaxiempty",_empty,True];
	if (_debug) then { diag_log format["TaxtGetOut: %1", _empty]; };
};

_vehicle setVariable ["airtaxiempty",False,True];
_vehicle addEventHandler ["getout",_fnTaxiGetOutHandler];

if (_debug) then { diag_log Format["(%1)[%2]: %3  player:%4",diag_tickTime,"airtaxiserver2.sqf","Heading to player", _player_pos]; };
[_vehicle, _player_pos, _flying_height, true, false] execVM "scripts\mando_heliroute_arma.sqf";
"d_airtaxi_marker" setMarkerPos position _vehicle;
"d_airtaxi_marker" setMarkerAlpha 1;
_vehicle spawn {
	While {alive _this} do {
		"d_airtaxi_marker" setMarkerPos position _this;
		sleep 3.512;
	};
	deletemarker "d_airtaxi_marker";
};

sleep 10;

if (isNil "_player" || _player == objNull) exitWith {
	["d_ataxi", [1,_player]] call XNetCallEvent;
	sleep 120;
	__del;
	_air_taxis = ["airtaxi_available",[]] call XNetGetJIP;
	if (_player in _air_taxis) then {
		_air_taxis = _air_taxis - [_player];
		["airtaxi_available",_air_taxis] call XNetSetJIP;
	};
};

["d_ataxi", [0,_player]] call XNetCallEvent;

_toldp = false;
while {_vehicle getVariable "mando_heliroute" == "busy"} do {
	if (_vehicle distance _player < (1000 + _flying_height) && alive _player && !_toldp) then {
		["d_ataxi", [6,_player]] call XNetCallEvent;
		_toldp = true;
	};
	sleep 2.012;
};

if ((isNil "_player" || _player == objNull) || (_vehicle getVariable "mando_heliroute" == "damaged")) exitWith {
	if (isNil "_player" || _player == objNull) then {
		["d_ataxi", [1,_player]] call XNetCallEvent;
	} else {
		["d_ataxi", [2,_player]] call XNetCallEvent;
	};
	sleep 120;
	__del;
	_air_taxis = ["airtaxi_available",[]] call XNetGetJIP;
	if (_player in _air_taxis) then {
		_air_taxis = _air_taxis - [_player];
		["airtaxi_available",_air_taxis] call XNetSetJIP;
	};
};
if (alive _vehicle) then {
	["d_ataxi", [8,_player]] call XNetCallEvent;

	if (_debug) then { diag_log Format["(%1)[%2]: %3  player:%4",diag_tickTime,"airtaxiserver2.sqf","Arrived at player pos",_player]; };
	if (_vehicle getVariable "mando_heliroute" == "waiting") then {
		_startWait = time;
		while {alive _player && !(_player in crew _vehicle) && ((time - _startWait) < 300)} do {sleep 1.012};
		if (_debug) then { diag_log format["Done waiting for: %1 (%2)", _player,(time - _startWait)]; };
		_vehicle setVariable ["mando_heliroute","embarked"];
		_hasplayers = false;
		{
			if (isPlayer _x) exitWith {_hasplayers = true;};
		} foreach crew _vehicle;
		if (!_hasplayers) then {
			sleep 20;
			{
				if (isPlayer _x) exitWith {_hasplayers = true;};
				_x setCaptive false;
			} foreach crew _vehicle;
		};
		if (_debug) then { diag_log Format["(%1)[%2]: %3  crew:%4",diag_tickTime,"airtaxiserver2.sqf","Player in crew", crew _vehicle]; };
		If (_hasplayers) then {
			_vehicle setVariable ["airtaxiempty",False,True];
			if (_debug) then { diag_log format["Players on board: %1", crew _vehicle]; };
			["d_ataxi", [3,_player]] call XNetCallEvent;
			sleep 5 + random 5;
			["d_ataxi", [5,_player]] call XNetCallEvent;
			if (_debug) then { diag_log Format["(%1)[%2]: %3  waypoints:%4",diag_tickTime,"airtaxiserver2.sqf","Starting route to destination",count _target_route]; };
			[_vehicle, _target_route, _flying_height, true, false] execVM "scripts\mando_heliroute_arma.sqf";
			sleep 5;
			_empty_checked = 0;
			while {_vehicle getVariable "mando_heliroute" == "busy" && !(_vehicle getVariable "airtaxiempty")} do {
				_hasplayers = false;
				{
					if (isPlayer _x) exitWith {_hasplayers = true;};
				} foreach crew _vehicle;
				if (!_hasplayers) then {
					_empty_checked = _empty_checked + 1;
				};
				if (_empty_checked > 5) then {
					_vehicle setVariable ["mando_heliroute","cancel",true];
					_vehicle setVariable ["airtaxiempty",True,True];
				};
				sleep 2.012
			};
			if (_vehicle getVariable "mando_heliroute" == "damaged") then {
				["d_ataxi", [2,_player]] call XNetCallEvent;
				sleep 120;
				__del;
			}
			else
			{
				if (_vehicle getVariable "airtaxiempty") then {
					if (_debug) then { diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"airtaxiserver2.sqf","Empty vehicle", crew _vehicle]; };
					["d_ataxi", [11,_player]] call XNetCallEvent;
					[_vehicle, [_dstart_pos], _flying_height, false,false] execVM "scripts\mando_heliroute_arma.sqf";
					_startWait = time;
					while {(_vehicle getVariable "mando_heliroute" == "busy") && ((time - _startWait) < 600)} do {sleep 2.012};
					sleep 120;
					__del;
				} else {
					if (_debug) then { diag_log Format["(%1)[%2]: %3  player:%4",diag_tickTime,"airtaxiserver2.sqf","Arrived at destination",_player]; };
					if (_vehicle getVariable "mando_heliroute" == "waiting") then {
						while {_player in crew _vehicle} do {sleep 3.012};
						if (_debug) then { diag_log Format["(%1)[%2]: %3  crew:%4",diag_tickTime,"airtaxiserver2.sqf","Player not in crew", crew _vehicle]; };
						sleep 10 + random 5;
						["d_ataxi", [4,_player]] call XNetCallEvent;
						
						if (_debug) then { diag_log Format["(%1)[%2]: %3  player:%4",diag_tickTime,"airtaxiserver2.sqf","Return to base",_dstart_pos]; };
						[_vehicle, [_dstart_pos], _flying_height, false,false] execVM "scripts\mando_heliroute_arma.sqf";
						_startWait = time;
						while {(_vehicle getVariable "mando_heliroute" == "busy") && ((time - _startWait) < 600)} do {sleep 2.012};
						sleep 120;
						__del;
					};
				};
			};
		} else {
			if (_debug) then { diag_log format["No players on board: %1", crew _vehicle]; };
			["d_ataxi", [11,_player]] call XNetCallEvent;
			[_vehicle, [_dstart_pos], 80, false] execVM "scripts\mando_heliroute_arma.sqf";
			sleep 120;
			_vehicle setVariable ["mando_heliroute","cancel",true];
			sleep 30;
			__del;
		};
	};
	if (alive _vehicle) then { ["d_ataxi", [9,_player]] call XNetCallEvent; };
};
_air_taxis = ["airtaxi_available",[]] call XNetGetJIP;
if (_debug) then { diag_log format["Remaining air taxis: %1", _air_taxis]; };
if (_player in _air_taxis) then {
	_air_taxis = _air_taxis - [_player];
	["airtaxi_available",_air_taxis] call XNetSetJIP;
};